from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.generics import ListAPIView, CreateAPIView, RetrieveAPIView
from rest_framework.viewsets import ViewSet

from . import models
from .serislizer import SmsCodeSerializer, LoginModelSerializer, \
    TopicModelSerializer, IndexDataModelSerializer, ReleaseModelSerializer, IndexDetailDataModelSerializer, \
    CommentModelSerializer, PostCommentModelSerializer, ThumbsModelSerializer, AuctionModelSerializer, \
    AuctionDetailModelSerializer, AuctionItemDetailModelSerializer, AuctionDepositModelSerializer, \
    BidRecordModelSerializer
from .serislizer import CouponModelSerializer, CouponApplyModelSerializer, CouponUserSerializer
from .serislizer import OrderSerializer, OrderDetailSerializer
from utils.centent.cos import credential
from utils.private import filters, pagination

from utils.auth import LoginAuthentication, PublicAuthentication
from django.db.models import F
from django.db.models import Max


class LoginAPIView(APIView):
    """登录"""

    def post(self, request, *args, **kwargs):
        # 有则更新token，无则创建
        login_ser_obj = LoginModelSerializer(data=request.data)
        if login_ser_obj.is_valid():
            # print(login_ser_obj.data)
            phone = login_ser_obj.context['phone']
            token = login_ser_obj.context['token']
            bucket = login_ser_obj.context['bucket']
            region = login_ser_obj.context['region']
            id = login_ser_obj.context['id']
            return Response({"status": 200, "msg": "ok",
                             "data":
                                 {"phone": phone, "token": token, "bucket": bucket, "region": region, "id": id}
                             },
                            status=status.HTTP_200_OK)
        return Response({"status": 400, "msg": "失败", "error": login_ser_obj.errors}, status=status.HTTP_400_BAD_REQUEST)


class SmsCodeAPIView(APIView):
    """
    发送短信
    """

    def post(self, request, *args, **kwargs):
        smm_ser_obj = SmsCodeSerializer(data=request.data)
        if smm_ser_obj.is_valid():
            return Response({'status': 200, "msg": "ok", "data": ""}, status=status.HTTP_200_OK)
        return Response({'status': 400, "msg": "失败", "error": smm_ser_obj.errors}, status=status.HTTP_400_BAD_REQUEST)


class TopicListAPIView(ListAPIView):
    """话题获取"""
    queryset = models.Topic.objects.filter(is_show=True, is_delete=False).order_by('order')
    serializer_class = TopicModelSerializer


class MomentAPIView(APIView):
    """临时密钥生成"""

    def get(self, request, *args, **kwargs):
        phone = request.query_params.get('phone')
        if not phone:
            return Response('手机号错误')
        user_obj = models.UserInfo.objects.get(phone=phone)
        bucket = user_obj.bucket
        # print(bucket)
        data = credential(bucket=bucket)
        return Response(data=data)


class PublishDataAPIView(APIView):
    """发布页面的数据保存(v1)"""

    def post(self, request, *args, **kwargs):
        # 存储发布表
        phone = request.data.get('phone')
        user_obj = models.UserInfo.objects.get(phone=phone)
        # 获取当前用户
        if not user_obj:
            return Response({"status": 400, "msg": "失败", "error": '用户不存在'}, status=status.HTTP_400_BAD_REQUEST)
        # print(request.data)
        position = request.data.get('position', '该用户没有提供位置信息')

        content = request.data.get('content', None)
        if not content:
            return Response({"status": 400, "msg": "失败", "error": '内容不能为空哦'}, status=status.HTTP_400_BAD_REQUEST)

        topic_id = request.data.get('topic', None)
        if not topic_id:
            return Response({"status": 400, "msg": "失败", "error": '必须选择话题哦'}, status=status.HTTP_400_BAD_REQUEST)

        # 创建发布表
        release_obj = models.Release.objects.create(
            **{
                "position": position,
                "content": content,
                "userinfo": user_obj,
                "topic_id": topic_id
            }
        )
        cos_data = request.data.get('cos_data')
        # 如果没有cos_data(是一个列表) 说明没有发布图片/视频，就不用创建
        if cos_data:
            # 循环cos_data进行创建media表
            # print(request.data)
            for item in cos_data:
                cosUrl = item.get('cosUrl')
                tail = cosUrl.split('/')[-1].split('.')[-1][-1]
                if tail == 'g':
                    name = '图片'
                    type = 2
                else:
                    name = '视频'
                    type = 3
                cosETag = item.get('cosETag')
                cos_media_name = item.get('cos_media_name')
                release = release_obj
                models.Media.objects.create(
                    **{
                        'name': name,
                        'type': type,
                        'cosUrl': cosUrl,
                        'release': release,
                        'cosETag': cosETag,
                        'cos_media_name': cos_media_name
                    }
                )

        return Response({"status": 200, "msg": "成功", "data": ''}, status=status.HTTP_200_OK)


class PublishDataAPIView2(CreateAPIView):
    """最新版上传v2"""
    # queryset = models.Release.objects.filter(is_show=True, is_delete=False)
    serializer_class = ReleaseModelSerializer


"""
{'position': '河南省驻马店市正阳县东大街2号', 'content': 'caCSCS', 'topic': 2, 'phone': '19803630852', 
'cos_data': [{'cosUrl': '19803630852-1645427981-1305448189.cos.ap-chengdu.myqcloud.com/003.png', 'cosETag': '"bcf6036d14edc516a8ac83b76d3cc4f7"'}, 
{'cosUrl': '19803630852-1645427981-1305448189.cos.ap-chengdu.myqcloud.com/103.png', 'cosETag': '"4580b0dd8d42b1cb313db0130a695745"'}]}


19803630852-1645427981-1305448189.cos.ap-chengdu.myqcloud.com/c1os964j1645516573181.png
19803630852-1645427981-1305448189.cos.ap-chengdu.myqcloud.com/c1os964j1645516573181.png
"""


class IndexDataListAPIView(ListAPIView):
    """首页展示信息"""
    queryset = models.Release.objects.filter(is_show=True, is_delete=False).order_by('-id')
    serializer_class = IndexDataModelSerializer

    filter_backends = [filters.MaxFilterBackend, filters.MinFilterBackend]
    pagination_class = pagination.DataLimitPagination


class IndexDetailRetrieveAPIView(RetrieveAPIView):
    """详情页信息展示"""
    queryset = models.Release.objects.filter(is_show=True, is_delete=False)
    serializer_class = IndexDetailDataModelSerializer

    def retrieve(self, request, *args, **kwargs):

        response = super(IndexDetailRetrieveAPIView, self).retrieve(request, *args, **kwargs)
        if not request.user:
            return response
        # 判断当前用户是否访问过
        new_obj = self.get_object()  # models.Replace.object.get(pk=pk)
        # print('obnj', new_obj)
        exist = models.WatchNum.objects.filter(userinfo=request.user, new=new_obj).exists()
        # 没有访问过，添加访问记录
        if not exist:
            # 给动态表添加数量
            models.Release.objects.filter(id=new_obj.id).update(watch_num=F('watch_num') + 1)
            # 给浏览表添加用户
            models.WatchNum.objects.create(
                userinfo=request.user,
                new=new_obj
            )
        return response


class CommentAPIView(APIView):
    """获取更多评论"""

    def get_authenticators(self):
        # 重写认证类
        if self.request.method == 'POST':
            return [LoginAuthentication(), ]
        return [PublicAuthentication(), ]

    def get(self, request, *args, **kwargs):
        """获取更多评论，通过root"""
        # print('1', request.user)
        root = int(request.query_params.get('root'))
        # print(root)
        queryset = models.Comment.objects.filter(root=root)
        # print(queryset)
        ser = CommentModelSerializer(instance=queryset, many=True)
        return Response(data=ser.data)

    def post(self, request, *args, **kwargs):
        """保存评论数据"""
        ser = PostCommentModelSerializer(data=request.data)  # ...
        # print(request.data)
        # {'comment': 'dada', 'new': 2, 'depth': 1}
        if ser.is_valid():
            # 在保存的时候手动赋值一个值
            ser.save(userinfo_id=request.user.id)
            # 评论数+1
            new_id = ser.validated_data.get('new').id
            models.Release.objects.filter(id=new_id).update(release_num=F('release_num') + 1)
            return Response(ser.data, status=status.HTTP_201_CREATED)
        return Response(ser.errors, status=status.HTTP_400_BAD_REQUEST)


class ThumbsAPIView(APIView):
    """点赞"""
    authentication_classes = [LoginAuthentication]

    def post(self, request, *args, **kwargs):
        ser = ThumbsModelSerializer(data=request.data)
        # 没有通过400
        if not ser.is_valid():
            return Response({}, status=status.HTTP_400_BAD_REQUEST)
        # 查询当前用户是否点过赞，点过删除，未点过，添加&数量加1
        query_set = models.ReleaseUp.objects.filter(userinfo=request.user, new=ser.validated_data.get('new'))
        if query_set:
            # 如果点过，删除
            # 发布数量加一
            models.Release.objects.filter(userinfo=request.user, id=ser.validated_data.get('new').id).update(
                release_up=F('release_up') - 1)
            query_set.delete()
            return Response({}, status=status.HTTP_200_OK)
        else:
            # 创建记录
            models.ReleaseUp.objects.create(
                userinfo=request.user, new=ser.validated_data.get('new')
            )
            # 发布数量加一
            models.Release.objects.filter(userinfo=request.user, id=ser.validated_data.get('new').id).update(
                release_up=F('release_up') + 1)
            return Response({}, status=status.HTTP_201_CREATED)


class AuctionDataView(ListAPIView):
    """拍卖列表"""
    queryset = models.Auction.objects.filter(status__gt=1).order_by('-id')
    # queryset = models.Auction.objects.filter().order_by('-id')
    serializer_class = AuctionModelSerializer


class AuctionDetailView(RetrieveAPIView):
    """拍卖场详细 前端传过来，相应的拍卖场id"""
    # RetrieveAPIView 会在查询条件最后面拼接一个pk
    queryset = models.Auction.objects.filter(status__gt=1)
    serializer_class = AuctionDetailModelSerializer

    def retrieve(self, request, *args, **kwargs):
        # 重写父类，添加其他的逻辑
        response = super(AuctionDetailView, self).retrieve(request, *args, **kwargs)
        # 判断当前用户是否登录
        user = request.user
        # 获取当前拍卖场的pk
        pk = kwargs.get('pk')
        # print(pk)
        if user:
            # 登录浏览表添加一条记录
            models.BrowseRecordAuction.objects.get_or_create(user=user, item_id=pk)
            # Auction表围观数量+1
            models.Auction.objects.filter(id=pk).update(look_count=F('look_count') + 1)
        return response

# 有问题--这个是全部商品的接口
class AuctionItemDetailView(RetrieveAPIView):
    """拍品商品详细,前端传过来，相应的商品id"""
    queryset = models.AuctionItem.objects.filter(status__gt=1)
    serializer_class = AuctionItemDetailModelSerializer

    def retrieve(self, request, *args, **kwargs):
        response = super(AuctionItemDetailView, self).retrieve(request, *args, **kwargs)
        pk = kwargs.get('pk')
        user_obj = request.user
        if user_obj:
            models.BrowseRecord.objects.get_or_create(user=user_obj, item_id=pk)
            # 商品记录加一
            models.AuctionItem.objects.filter(pk=pk).update(look_count=F('look_count') + 1)
        return response


class AuctionDepositView(RetrieveAPIView):
    """保证金"""
    authentication_classes = [LoginAuthentication, ]
    queryset = models.AuctionItem.objects.filter(status__in=[2, 3])
    serializer_class = AuctionDepositModelSerializer


class AuctionBidView(ListAPIView, CreateAPIView):
    """竞价 www.xxxx.com/../../?item_id=1"""
    authentication_classes = [LoginAuthentication, ]
    queryset = models.BidRecord.objects.filter(status=1)
    serializer_class = BidRecordModelSerializer

    def get_queryset(self):
        # 进行过滤，找到当前出价的商品
        item_id = self.request.query_params.get('item_id')
        queryset = self.queryset.filter(item_id=item_id)
        return queryset

    def get(self, request, *args, **kwargs):
        # 重写get，构造返回的数据
        response = super(AuctionBidView, self).get(request, *args, **kwargs)
        # 序列化之后的数据
        # [OrderedDict([('id', 1), ('status', '竞价'), ('item', 2), ('user', 1)]), OrderedDict([('id', 2), ('status', '竞价'), ('item', 2), ('user', 1)])]
        # print(response.data)
        item_id = self.request.query_params.get('item_id')
        item_obj = models.AuctionItem.objects.filter(id=item_id).first()
        # 取最大价格，如果没有，取低价

        # 进行聚合，求出最大值，{'max_price':1200}
        max_price = models.BidRecord.objects.filter(status=1, item_id=item_id).aggregate(max_price=Max('price'))[
            'max_price']
        data = {
            'unit': item_obj.unit,
            'price': max_price or item_obj.start_price,
            'result': response.data
        }
        response.data = data
        return response

    def perform_create(self, serializer):
        # 在保存之前添加字段
        # 添加锁
        from django.db import transaction
        from rest_framework.exceptions import ValidationError
        with transaction.atomic():
            item_id = self.request.data.get('item_id')
            price = self.request.data.get('price')
            # 加锁，同一个价格只能一个出价  select_for_update
            result = models.BidRecord.objects.filter(status=1, item_id=item_id).aggregate(
                max_price=Max('price')).select_for_update()
            max_price = result.get('max_price')
            if price < max_price:
                raise ValidationError('价格不够！')
            serializer.save(user=self.request.user)


class CouponListView(ListAPIView):
    """优惠劵列表"""
    queryset = models.CouponStrength.objects.filter(is_delete=False, is_show=True).all().order_by('-id')
    serializer_class = CouponModelSerializer
    filter_backends = [filters.MaxFilterBackend, filters.MinFilterBackend]
    pagination_class = pagination.DataLimitPagination


class CouponApplyView(CreateAPIView):
    """领取优惠劵"""
    authentication_classes = [LoginAuthentication, ]
    serializer_class = CouponApplyModelSerializer

    # def perform_create(self, serializer):
    #     user_coupon = serializer.save(user=self.request.user)
    #     # 在保存以后，添加过期时间


from collections import OrderedDict


class CouponUserView(ListAPIView, CreateAPIView):
    """用户的优惠劵"""
    authentication_classes = [LoginAuthentication, ]
    serializer_class = CouponUserSerializer

    def get_queryset(self):
        queryset = models.UserCoupon.objects.filter(user=self.request.user, is_delete=False, is_show=True).order_by(
            '-id')
        return queryset

    def list(self, request, *args, **kwargs):
        response = super(CouponUserView, self).list(request, *args, **kwargs)
        # 如果有问题，报错
        if response.status_code != status.HTTP_200_OK:
            return response
        # 更改返回的格式 {1：{'text':'未使用',child:[] }}
        # 有序字典
        status_dict = OrderedDict()
        for item in models.UserCoupon.status_type:
            status_dict[item[0]] = {'text': item[1], 'child': []}

        for row in response.data:
            # print(row)
            status_dict[int(row['status'])]['child'].append(row)

        response.data = status_dict
        return response


# todo 优惠劵使用/前端拍卖场渲染/商品渲染/登录创建桶修改/保证金缴纳


class OrderView(ListAPIView):
    """用户订单展示"""
    authentication_classes = [LoginAuthentication, ]
    serializer_class = OrderSerializer

    def get_queryset(self):
        queryset = models.Order.objects.filter(userinfo=self.request.user).order_by(
            '-id')
        return queryset

    def list(self, request, *args, **kwargs):
        response = super().list(request, *args, **kwargs)
        # 如果有问题，报错
        if response.status_code != status.HTTP_200_OK:
            return response
        # 更改返回的格式 {1：{'text':'未使用',child:[] }}
        # 有序字典
        status_dict = OrderedDict()
        for item in models.Order.status_type:
            status_dict[item[0]] = {'text': item[1], 'child': []}

        for row in response.data:
            status_dict[int(row['status'])]['child'].append(row)

        response.data = status_dict
        return response


class OrderDetailView(RetrieveAPIView):
    """订单详细列表"""
    authentication_classes = [LoginAuthentication, ]
    # queryset = models.Order.objects.all()
    serializer_class = OrderDetailSerializer

    def get_queryset(self):
        queryset = models.Order.objects.filter(userinfo=self.request.user)
        models.UserCoupon.objects.filter()
        return queryset
